#!/usr/bin/perl
# Version 0.2.1

$testcase = "seq_num_mismatch";

# 1 = PASS
# 2 = FAIL
# 3 = INCONCLUSIVE
$verdict = 3;

$dumpfile = "$testcase.dump";
$logfile = "$testcase.log";

if ($#ARGV ne 8) {
        print("Usage: $testcase.pl dump_file1 ... dump_file8 log_file");
        exit 1;
}

for( $i = 0; $i < 8; $i++) {
	$dumpfile[$i] = $ARGV[$i];
}
$logfile = $ARGV[8];

#------------------------------------------------------------------------------

@local_verdict = ( 3, 3, 3, 3, 3, 3, 3, 3 );

$success = 1;
$state = 0;
open(DUMPFILE, $dumpfile[0]) or $success = 0;

if($success) {
	while(<DUMPFILE>) {
		if($state eq 0) {
			if(/0\.0\.1\.58 > (.*) OSPFv2-dd (.*) backbone (.*) S /) {
				@bits = split(/ /, $3);
				if($bits[0] ne "E") {
					# found the packet from TR with the E-bit clear
					# the next dd-packet from the RUT must have the I bit set
					$state = 1;
				}
			}
		}
		if($state eq 1) {
			if(/0\.0\.1\.57 > (.*) OSPFv2-dd (.*) backbone E (.*) S /) {
				# this is the next dd-packet from the RUT
				@bits = split(/\//, $3);
				if($bits[0] ne "I") {
					$state = 2;
				} else {
					$state = 3;
				}
			}
		}
	}
	
	if($state eq 3) {
		$local_verdict[0] = 1;
	} else {
		$local_verdict[0] = 2;
	}
}

$success = 1;
$state = 0;

open(DUMPFILE, $dumpfile[1]) or $success = 0;

if($success) {
	
	while(<DUMPFILE>) {
		if($state < 2) {
			# wait for the second dd-packet from 0.0.1.50 with the I bit set
			if(/0\.0\.1\.50 > (.*) OSPFv2-dd (.*) backbone E (.*) S /) {
				@bits = split(/\//, $3);
				if($bits[0] eq "I") {
					$state++;
				}
			}
		}
		if($state eq 2) {
			# the next dd-packet from 0.0.1.49 must also have the I bit set
			if(/0\.0\.1\.49 > (.*) OSPFv2-dd (.*) backbone E (.*) S /) {
				# this is the next dd-packet from the RUT
				@bits = split(/\//, $3);
				if($bits[0] ne "I") {
					$state = 3;
				} else {
					$state = 4;
				}
			}
		}
	}
	
	if($state eq 4) {
		$local_verdict[1] = 1;
	} else {
		$local_verdict[1] = 2;
	}
}

$success = 1;
$state = 0;
open(DUMPFILE, $dumpfile[2]) or $success = 0;

if($success) {
	while(<DUMPFILE>) {
		if($state < 2) {
			# wait for the second non-initial dd-packet from 0.0.1.42
			if(/0\.0\.1\.42 > (.*) OSPFv2-dd (.*) backbone E (.*) S /) {
				@bits = split(/\//, $3);
				if($bits[0] ne "I") {
					$state++;
				}
			}
		}
		if($state eq 2) {
			# now wait fr the next dd packet from the tr - this is the one that has the seq. no
			# set too high.
			if(/0\.0\.1\.42 > (.*) OSPFv2-dd /) {
				$state++;
			}
			
		}
		if($state eq 3) {
			# the next dd-packet from 0.0.1.41 must also have the I bit set
			if(/0\.0\.1\.41 > (.*) OSPFv2-dd (.*) backbone E (.*) S /) {
				# this is the next dd-packet from the RUT
				@bits = split(/\//, $3);
				if($bits[0] ne "I") {
					$state = 4;
				} else {
					$state = 5;
				}
			}
		}
	}
	
	if($state eq 5) {
		$local_verdict[2] = 1;
	} else {
		$local_verdict[2] = 2;
	}
}

$success = 1;
$state = 0;
open(DUMPFILE, $dumpfile[3]) or $success = 0;

if($success) {
	while(<DUMPFILE>) {
		if($state < 2) {
			# wait for the second non-initial dd-packet from 0.0.1.34
			if(/0\.0\.1\.34 > (.*) OSPFv2-dd (.*) backbone E (.*) S /) {
				@bits = split(/\//, $3);
				if($bits[0] ne "I") {
					$state++;
				}
			}
		}
		if($state eq 2) {
			# now wait for the next dd packet from the tr - this is the one that has the seq. no
			# set too high.
			if(/0\.0\.1\.34 > (.*) OSPFv2-dd /) {
				$state++;
			}
			
		}
		if($state eq 3) {
			# the next dd-packet from 0.0.1.33 must also have the I bit set
			if(/0\.0\.1\.33 > (.*) OSPFv2-dd (.*) backbone E (.*) S /) {
				# this is the next dd-packet from the RUT
				@bits = split(/\//, $3);
				if($bits[0] ne "I") {
					$state = 4;
				} else {
					$state = 5;
				}
			}
		}
	}
	
	if($state eq 5) {
		$local_verdict[3] = 1;
	} else {
		$local_verdict[3] = 2;
	}
}

$success = 1;
$state = 0;
open(DUMPFILE, $dumpfile[4]) or $success = 0;

if($success) {
	while(<DUMPFILE>) {
		if($state eq 0) {
			# wait for the first non-initial dd-packet from 0.0.1.25
			if(/0\.0\.1\.25 > (.*) OSPFv2-dd (.*) backbone E (.*) S /) {
				@bits = split(/\//, $3);
				if($bits[0] ne "I") {
					$state++;
				}
			}
		}
		if($state eq 1) {
			# now wait for the next dd packet from the tr - this is the one that has the MS bit
			# manipulated
			if(/0\.0\.1\.26 > (.*) OSPFv2-dd /) {
				$state++;
			}
			
		}
		if($state eq 2) {
			# the next dd-packet from 0.0.1.25 must also have the I bit set
			if(/0\.0\.1\.25 > (.*) OSPFv2-dd (.*) backbone E (.*) S /) {
				# this is the next dd-packet from the RUT
				@bits = split(/\//, $3);
				if($bits[0] ne "I") {
					$state = 3;
				} else {
					$state = 4;
				}
			}
		}
	}
	
	if($state eq 4) {
		$local_verdict[4] = 1;
	} else {
		$local_verdict[4] = 2;
	}
}

$success = 1;
$state = 0;
open(DUMPFILE, $dumpfile[5]) or $success = 0;

if($success) {
	while(<DUMPFILE>) {
		if($state eq 0) {
			# wait for the first dd-packet from 0.0.1.18 after 50 seconds
			if(/(.* )0\.0\.1\.18 > (.*) OSPFv2-dd/) {
				
				# now look at the time
				@ti = split(/\./, $1);
				@ts = split(/:/, $ti[0]);
			
				$secs = $ts[2] + ($ts[1] + $ts[0] * 60) * 60; # secs contains the sim time in seconds
		
				if ($secs > 50) {
					$state++;
				}
			}
		}
		if($state eq 1) {
			# now wait for the next dd packet from the tr - this is the late dd packet
			if(/0\.0\.1\.18 > (.*) OSPFv2-dd /) {
				$state++;
			}
			
		}
		if($state eq 2) {
			# the next dd-packet from 0.0.1.17 must also have the I bit set
			if(/0\.0\.1\.17 > (.*) OSPFv2-dd (.*) backbone E (.*) S /) {
				# this is the next dd-packet from the RUT
				@bits = split(/\//, $3);
				if($bits[0] ne "I") {
					$state = 3;
				} else {
					$state = 4;
				}
			}
		}
	}
	
	# default is FAIL  if there has been no dd packet from RUT in response to the late packet
	$local_verdict[5] = 2;
	
	if($state eq 4) {
		$local_verdict[5] = 1;
	} else {
		$local_verdict[5] = 2;
	}
}

$success = 1;
$state = 0;
open(DUMPFILE, $dumpfile[6]) or $success = 0;

if($success) {
	while(<DUMPFILE>) {
		if($state eq 0) {
			# wait for the first non-initial dd-packet from 0.0.1.9
			if(/0\.0\.1\.9 > (.*) OSPFv2-dd (.*) backbone E (.*) S /) {
				@bits = split(/\//, $3);
				if($bits[0] ne "I") {
					$state++;
				}
			}
		}
		if($state eq 1) {
			# now wait for the next dd packet from the tr - this is the one that has the 
			# LSA with unknown type in it
			if(/0\.0\.1\.10 > (.*) OSPFv2-dd /) {
				$state++;
			}
			
		}
		if($state eq 2) {
			# the next dd-packet from 0.0.1.9 must have the I bit set
			if(/0\.0\.1\.9 > (.*) OSPFv2-dd (.*) backbone E (.*) S /) {
				# this is the next dd-packet from the RUT
				@bits = split(/\//, $3);
				if($bits[0] ne "I") {
					$state = 3;
				} else {
					$state = 4;
				}
			}
		}
	}
	
	if($state eq 4) {
		$local_verdict[6] = 1;
	} else {
		$local_verdict[6] = 2;
	}
}

# not implemented yet - AS external LSAs not supported yet
#$success = 1;
#$state = 0;
#open(DUMPFILE, $dumpfile[7]) or $success = 0;
#
#if($success) {
#	while(<DUMPFILE>) {
#		
#	}
#}


# generate report
if ($local_verdict[0] eq 1) {
	print("RUT returns to EXSART when options change. Test PASSED.\n");
} elsif ($local_verdict[0] eq 2) {
	print("RUT doesn't return to EXSTART when options change. Test FAILED.\n");
} else {
	print("Cannot evaluate test results. Test INCONCLUSIVE.\n");
}

if ($local_verdict[1] eq 1) {
	print("RUT returns to EXSTART when I bit is set. Test PASSED.\n");
} elsif ($local_verdict[1] eq 2) {
	print("RUT does not return to EXSTART when I bit is set. Test FAILED.\n");
} else {
	print("Cannot evaluate test results. Test INCONCLUSIVE.\n");
}

if ($local_verdict[2] eq 1) {
	print("RUT returns to EXSTART when seq.no. too high. Test PASSED.\n");
} elsif ($local_verdict[2] eq 2) {
	print("RUT does not return to EXSTART when seq.no. too high. Test FAILED.\n");
} else {
	print("Cannot evaluate test results. Test INCONCLUSIVE.\n");
}

if ($local_verdict[3] eq 1) {
	print("RUT returns to EXSTART when seq.no. too low. Test PASSED.\n");
} elsif ($local_verdict[3] eq 2) {
	print("RUT does not return to EXSTART when seq.no. too low. Test FAILED.\n");
} else {
	print("Cannot evaluate test results. Test INCONCLUSIVE.\n");
}

if ($local_verdict[4] eq 1) {
	print("RUT returns to EXSTART when MS bit is changed. Test PASSED.\n");
} elsif ($local_verdict[4] eq 2) {
	print("RUT does not return to EXSTART when MS bit is changed. Test FAILED.\n");
} else {
	print("Cannot evaluate test results. Test INCONCLUSIVE.\n");
}

if ($local_verdict[5] eq 1) {
	print("RUT returns to EXSTART when receiving a late DD packet. Test PASSED.\n");
} elsif ($local_verdict[5] eq 2) {
	print("RUT does not return to EXSTART when receiving a late DD packet. Test FAILED.\n");
} else {
	print("Cannot evaluate test results. Test INCONCLUSIVE.\n");
}

if ($local_verdict[6] eq 1) {
	print("RUT returns to EXSTART when receiving an unknown LS type. Test PASSED.\n");
} elsif ($local_verdict[6] eq 2) {
	print("RUT does not return to EXSTART when receiving an unknown LS type. Test FAILED.\n");
} else {
	print("Cannot evaluate test results. Test INCONCLUSIVE.\n");
}

if ($local_verdict[7] eq 1) {
	print("RUT returns to EXSTART when receiving AS-external LSAs in stub area. Test PASSED.\n");
} elsif ($local_verdict[7] eq 2) {
	print("RUT does not return to EXSTART when receiving AS-external LSAs in stub area. Test FAILED.\n");
} else {
	print("OSPF doesn't support AS-external LSAs yet. Test INCONCLUSIVE.\n");
}

$verdict = $local_verdict[0];
for($i = 1; $i < 8; $i++) {
	if ($local_verdict[$i] ne $verdict) {
		if($local_verdict[$i] eq 2) {
			$verdict = 2;
		} elsif ($local_verdict[$i] eq 3) {
			if($verdict ne 2) {
				$verdict = 3;
			}
		}	
	}
}

#------------------------------------------------------------------------------
print("### VERDICT for $testcase: ");

if ($verdict eq 1) { 
        print("PASS"); 
} elsif ($verdict eq 2) {
        print("FAIL");
} else {
        print("INCONCLUSIVE");
}

print(" ###\n");